package com.boot.security.model.ao;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description 图工具
 * @date 2020/2/19 17:52
 **/

public class NodeUtil {

    public static <T> Node<T> create(T o) {
        return Node.<T>builder().element(o).parent(new ArrayList<>()).children(new ArrayList<>()).build();
    }

    public static <T> Collection<Node<T>> create(Collection<T> collection) {
        if (CollectionUtils.isEmpty(collection)) {
            return new ArrayList<>();
        } else {
            return collection.stream().map(item -> Node.<T>builder().element(item).parent(new ArrayList<>()).children(new ArrayList<>()).build())
                    .collect(Collectors.toList());
        }
    }

    public static <T> boolean contains(Collection<Node<T>> collection, Node<T> node) {
        if (!CollectionUtils.isEmpty(collection) && node != null) {
            for (Node<T> item : collection) {
                if (node.getElement().equals(item.getElement())) {
                    return true;
                }
            }
        }
        return false;
    }

    public static <T> Node<T> get(Collection<Node<T>> collection, Predicate<T> predicate) {
        if (null != collection) {
            for (Node<T> node : collection) {
                if (null != node && predicate.test(node.getElement())) {
                    return node;
                }
            }
        }
        return null;
    }

    public static <T> void put(Collection<Node<T>> collection, Node<T> node) {
        if (!CollectionUtils.isEmpty(collection) && node != null) {
            if (!contains(collection, node)) {
                collection.add(node);
            }
        }
    }

    public static <T> Collection<Node<T>> parent(Node<T> node) {
        Collection<Node<T>> parent = node.getParent();
        Set<Node<T>> result = new HashSet<>(parent);
        if (!CollectionUtils.isEmpty(parent)) {
            for (Node<T> item : parent) {
                parent(result, item);
            }
        }
        return parent;
    }

    private static <T> void parent(Collection<Node<T>> result, Node<T> node) {
        Collection<Node<T>> parent = node.getParent();
        result.addAll(parent);
        if (!CollectionUtils.isEmpty(parent)) {
            for (Node<T> item : parent) {
                parent(result, item);
            }
        }
    }

    public static <T> Collection<Node<T>> children(Node<T> node) {
        Collection<Node<T>> children = node.getChildren();
        Set<Node<T>> result = new HashSet<>(children);
        if (!CollectionUtils.isEmpty(children)) {
            for (Node<T> item : children) {
                parent(result, item);
            }
        }
        return children;
    }

    private static <T> void children(Collection<Node<T>> result, Node<T> node) {
        Collection<Node<T>> children = node.getChildren();
        result.addAll(children);
        if (!CollectionUtils.isEmpty(children)) {
            for (Node<T> item : children) {
                parent(result, item);
            }
        }
    }

}
